<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>call和bind和apply的区别</title>
  </head>
  <body></body>
  <script>
    // 相同点
    // 都会改变 this 的指向
    // 不同点
    // 1. bind：在修改函数 this 时，会产生新的函数，新函数在任何状态执行时，内部 this 永远为固定的 this 值
    // 2. call/apply：在函数调用时，修改函数内部 this 的值
    //      call和apply 的第一个参数都是要绑定的新的 this 值，
    //      call  方法的剩余参数是原本要传递到执行函数的参数
    //      apply 方法的第二个参数是将原本要传递到执行函数的参数合并成的数组

    function fn(x, y) {
      console.log(this, x, y);
      // 浏览环境下，声明式函数 this 默认指向全局对象 window
    }
    fn(1, 2);

    const obj = { m: 0 };

    // bind 在修改 this 时返回一个新函数
    // 执行时 参数1 为新函数绑定的 this 值，剩余参数是为新函数绑定的 参数值
    let f1 = fn.bind(obj);
    f1(1, 2); // obj, 1, 2
    let f2 = fn.bind(obj, 3);
    f2(4, 5); // obj, 3, 4
    let f3 = fn.bind(obj, 6, 7);
    f3(8, 9); // obj, 6, 7

    // call/apply 在修改函数 this 值时会直接执行函数
    fn.call(obj, 1, 2);
    fn.apply(obj, [1, 2]);

    // 注意：如果执行的新 this 值是 null/undefined, 函数内部会自动修正为 window
    fn.call(null, 3, 4);
  </script>
</html>
